﻿using MaterialDesignThemes.Wpf;
using Prism.Ioc;
using Prism.Mvvm;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace DailyApp.WPF.Service
{
    /// <summary>
    /// 这段代码通过继承Prism服务 + 委托MD控件实现 + 接口约束，实现了两大框架的无缝桥接。
    /// 主题一致性由WPF资源继承和MD样式体系自然保障，无需显式编码。这种设计保留了Prism的DI/模块化优势，同时获得MD的现代化UI体验。
    /// </summary>
    internal class DialogHostService : DialogService
    {
        private readonly IContainerExtension containerExtension;

        /// <summary>
        /// 构造函数
        /// </summary>
        public DialogHostService(IContainerExtension containerExtension) : base(containerExtension)
        {
            this.containerExtension = containerExtension;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="name">窗体名</param>
        /// <param name="parameters">传递参数</param>
        /// <param name="dialogHostName">父级主机名</param>
        /// <returns>异步阻塞结束返回按钮点击结果</returns>
        public async Task<IDialogResult> ShowDialog(string name, IDialogParameters parameters, string dialogHostName = "RootDialog")
        {
            if (parameters == null)
                parameters = new DialogParameters();

            //从容器当中去除弹出窗口的实例
            var content = containerExtension.Resolve<object>(name);

            //验证实例的有效性 
            if (!(content is FrameworkElement dialogContent))
                throw new NullReferenceException("A dialog's content must be a FrameworkElement");

            //检测是否已手动配置VM，若无则自动配置,若有则不干扰原有配置(因为我们自定义了这个接口IDialogHostAware，因此无法使用prism框架的对话框注入,因此需要使用这种方式辅助配置)
            if (dialogContent is FrameworkElement view && view.DataContext is null && ViewModelLocator.GetAutoWireViewModel(view) is null)
                ViewModelLocator.SetAutoWireViewModel(view, true);

            if (!(dialogContent.DataContext is IDialogHostAware viewModel))
                throw new NullReferenceException("A dialog's ViewModel must implement the IDialogAware interface");

            DialogOpenedEventHandler eventHandler = (sender, eventArgs) =>
            {
                if (viewModel is IDialogHostAware aware)
                {
                    aware.OnDialogOpening(parameters);
                }
                eventArgs.Session.UpdateContent(content);
            };

            return (IDialogResult)await DialogHost.Show(dialogContent, dialogHostName, eventHandler);
        }
    }
}
